﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.Mvc;

namespace MvcImproved.Generic.Controls
{
	public class RenderPartial<TDataItem, TMemberValue> : GenericControl<TDataItem, TMemberValue>
	{
		public String ViewName
		{
			get;
			set;
		}

		public RenderPartial(Func<TDataItem, TMemberValue> valueMember)
			: base(valueMember)
		{ }

		protected override void Render(HtmlTextWriter writer)
		{
			InitViewData();
			ViewContext newViewContext;
			if (!DesignMode)
			{
				TMemberValue memberValue = (DataValue == null) ? default(TMemberValue) : ValueMemberLambda(DataValue);

				ViewDataDictionary<TMemberValue> newViewData;
				if (ViewData == null)
					newViewData = new ViewDataDictionary<TMemberValue>(memberValue);
				else
					newViewData = new ViewDataDictionary<TMemberValue>(ViewData) { Model = memberValue };

				newViewContext = new ViewContext(ViewContext, ViewContext.View, newViewData, ViewContext.TempData, writer);
			}
			else
				newViewContext = ViewContext;

			ViewEngineResult result = ViewEngines.Engines.FindPartialView(newViewContext, ViewName);
			if (result.View != null)
			{
				result.View.Render(newViewContext, writer);
				return;
			}

			StringBuilder locationsText = new StringBuilder();
			foreach (string location in result.SearchedLocations)
			{
				locationsText.AppendLine();
				locationsText.Append(location);
			}

			throw new InvalidOperationException(String.Format("Partial view '{0}' not found. Searched {1}", ViewName, locationsText));
		}
	}

	// Non-generic version of the control that's used in the actual markup
	[ControlBuilder(typeof(GenericControlBuilder))]
	[GenericControlType(typeof(RenderPartial<,>), MemberValue = "ValueMember", GenericParameters = "ModelType")]
	public class RenderPartial : RenderPartial<object, object>
	{
		public RenderPartial()
			: base(null)
		{ }

		public string ModelType
		{
			get;
			set;
		}
	}
}